#!/usr/bin/env ruby

require 'drb'
require 'lib/signal'

class RuDcCore
	include DRb::DRbUndumped
	include Signaling
	def initialize(port, host="",params=nil)
		@name=object_id.to_s
		@plugins={}
		@port=port
		@host=host
		@semaphore=Mutex.new

		@killPlugs=true

		#@ObjectSpace.define_finalizer
		Signal.trap("TERM",proc {
			puts("Sending all plugins TERM Signal")
				if @killPlugs
					@plugins.each_value {|plug|
						plug.selfKill
						puts(" --Plugin killed")
					}
				end
			DRb.stop_service
			puts "plugins dead"
			exit
		})

		@params = params==nil ? Hash.new : params
		params[:autorun]=true unless params.has_key?(:autorun)
		if params[:debugout]!=nil
			params[:debugout].puts "DEBUG ENABELED"
		end
		if params[:autorun]
			run
		end
	end
	
	def die
		if @killPlugs
			@plugins.each_value {|plug| plug.selfKill}
		end
		exit
	end

	def run
		puts "starting core.."
		DRb.start_service("druby://#{@host}:#{@port.to_s}", self,{:verbose=>true})
		puts "DRb server started"
		puts "Core online"
		DRb.thread.join
	end

	def register(plugin)
		@semaphore.synchronize {
		if @params[:selfdebug] then selfdebugmsg("Regisering plugin: "+plugin.method_missing(:class).to_s+" "+plugin.__drburi.to_s+"with pid:"+plugin.pid.to_s) end
		if @params[:debugout] then plugin.connect(:debugmsg,self,:parsedebugmsg) end
		@plugins[plugin.name]=plugin}
	end
	
	def unreg(plugin)
		@semaphore.synchronize {
			if @params[:selfdebug] then selfdebugmsg("Unegisering plugin: "+plugin.method_missing(:class).to_s+" "+plugin.__drburi.to_s) end
			@plugins.delete(plugin.name)
		}
	end

	def connectPlugs(nameA,msg,nameB,slot)
		@plugins[nameA].connect(msg,@plugins[nameB],slot)
	end

	def disconnectPlugs(nameA,msg,nameB,slot)
                 @plugins[nameA].disconnect(msg,@plugins[nameB],slot)
        end
		
	def runPlugin(name)
		if @plugins.has_key?(name)
			#@semaphore.synchronize{
			@plugins[name].runme
			#Process.detach(e)}
		else
			selfdebugmsg("Run plugin error: no such plugin - #{name}")
		end
	end

	def parsedebugmsg(msg)
		if @params[:debugout]!=nil
			@params[:debugout].puts "DEBUGMSG: "+msg.to_s
		end
	end

        def selfdebugmsg(msg)
		if @params[:selfdebug]!=nil
                	@params[:selfdebug].puts "SLFDEBUGMSG: "+msg.to_s
		end
         end


	def wait_for
		DRb.thread.join
	end

	def registred?(name)
		@semaphore.synchronize{
		return @plugins.has_key?(name)
		}
	end


	attr_accessor :plugins
	attr_accessor :debugout

end

def wait_register(core,plugin)
	while not core.registred?(plugin)
		sleep 1
	end
end

def startPlugin(plugClass,coreURI,name,*args)
	puts "Starting: #{plugClass.to_s} with URI #{coreURI} and name #{name}"
	pid=fork{plugClass.new(*([coreURI]+[name]+args))}
	core=DRbObject.new(nil,coreURI)
	wait_register(core,name)
end


if __FILE__==$0
	$:.push("./plugins")
	$:.push("./lib")
	require 'plugins/dchub.rb'
	require 'plugins/logger.rb'
	corepid=fork {
		core=RuDcCore.new(1555)
		core.run
	}
	sleep 2
	core=DRbObject.new(nil,"druby://localhost:1555")
	#log=fork {log=DCLogger.new("druby://localhost:1555","testlog")}
	#wait_register(core,"testlog")	
        #dc=fork {dc=DCHub.new("druby://localhost:1555","testhub","dc.hovel.ru",411,user)}
	#wait_register(core,"testhub")
	startPlugin(DCHub,"druby://localhost:1555","testhub",{})
	startPlugin(DCLogger,"druby://localhost:1555","testlog")

	puts 'connecting...'
	core.connectPlugs("testhub",:chatmsg,"testlog",:write_log)

	puts 'connected.. forking run'
	core.runPlugin("testhub")

	core.wait_for
end
